package entity

import (
	"fmt"
	"gluenet/modules/manager/server/domain/po"
	"gluenet/modules/manager/server/domain/vo"
	"gluenet/modules/manager/server/infra"
	"gopkg.in/yaml.v3"
	"io/ioutil"
	"sync"
)

var (
	console map[string]map[string]interface{}
	appyaml map[string]map[string]interface{}
	once    sync.Once
)

func init() {
	once.Do(func() {
		bts, err := ioutil.ReadFile("/config/webssh.yml")
		if err != nil {
			fmt.Printf("error read webssh.yml")
		}
		console = make(map[string]map[string]interface{})
		err = yaml.Unmarshal(bts, console)
		if err != nil {
			fmt.Printf("error unmarshall webssh.yml")
		}

		bts2, err := ioutil.ReadFile("/config/app.yml")
		if err != nil {
			fmt.Printf("error read app.yml")
		}
		appyaml = make(map[string]map[string]interface{})
		err = yaml.Unmarshal(bts2, appyaml)
		if err != nil {
			fmt.Printf("error unmarshall app.yml")
		}
	})
}

type Instance struct {
	infra.Entity `xorm:"-"`
	po.Instance  `xorm:"extends"`
	Config       *Config   `xorm:"-"`
	Tags         []*po.Tag `xorm:"-"`
	Links        []Link    `xorm:"-"`
}

func (r *Instance) Identity() string {
	return r.GUID
}

func (r *Instance) MarkedTag(key, value string) error {
	return nil
}

func (r *Instance) AddLink(lk Link) error {
	r.Links = append(r.Links, lk)
	return nil
}

func (r *Instance) ShowInfo() *vo.InstanceInfoRes {
	info := &vo.InstanceInfoRes{
		GUID:             r.GUID,
		Name:             r.Name,
		ConfigID:         r.ConfigID,
		Label:            r.Label,
		Platform:         r.Platform,
		Version:          r.Version,
		Origin:           r.Origin,
		Describe:         r.Describe,
		Kind:             r.Kind,
		Links:            r.Links,
		DetailRepoValue:  r.DetailRepoValue,
		RunTimeRepoValue: r.RunTimeRepoValue,
		Created:          r.Created,
		Updated:          r.Updated,
	}

	if _, ok := console[info.ConfigID]; ok {
		info.Terminal = console[info.ConfigID]
	} else {
		info.Terminal = map[string]interface{}{
			"ssh": "39.101.140.145:30006",
			"console": map[string]string{
				"ip":       "39.101.140.145",
				"port":     "63901",
				"username": "tsb",
				"passwd":   "123456",
			},
		}
	}

	return info
}

type svc struct {
	PerfermanceEnable string `json:"perfermance_enable"`
	AppEnable         string `json:"app_enable"`
	App               string `json:"app"`
}

func (r *Instance) ShowRuntimeInfo() (*vo.InstanceRuntimeRes, error) {
	run := &vo.InstanceRuntimeRes{
		GUID:           r.GUID,
		Name:           r.Name,
		Platform:       r.Platform,
		Version:        r.Version,
		Describe:       r.Describe,
		UsedCores:      10,
		AvgMemUsed:     10,
		ErrorLogsCount: 12,
		CreateTime:     r.Created.Unix(),
		Containers:     make(map[string]interface{}),
	}
	rrv, ok := r.RunTimeRepoValue.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("runtime repo value is not map[string]interface{}")
	}

	containerStatei, ok := rrv["state"]
	if !ok {
		return nil, fmt.Errorf("runtime repo value not contian state")
	}
	status, ok := containerStatei.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("status value is not map[string]interface{}")
	}

	drv, ok := r.DetailRepoValue.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("detail repo value is not map[string]interface{}")
	}

	var dSpec map[string]interface{}
	if r.Platform == PlatformGluenets {
		dSpeci, ok := drv["spec"]
		if !ok {
			return nil, fmt.Errorf("runtime repo value not contian spec")
		}
		dSpec, ok = dSpeci.(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("spec value is not map[string]interface{}")
		}
	}

	//fmt.Printf("state %v\n",status)

	for name, state := range status {
		servive := svc{
			PerfermanceEnable: infra.Disable,
			AppEnable:         infra.Disable,
			App:               "",
		}
		if state.(int) == infra.Ready && r.Platform == PlatformGluenets {
			platfromSrvi, ok := dSpec["platform_service"]
			if ok {
				srvi, ok := platfromSrvi.(map[string]interface{})
				if ok {
					cprofilei, ok := srvi["cprofile"]
					if ok {
						cprofile, ok := cprofilei.(map[string]interface{})
						if ok {
							c, exist := cprofile[name]
							if exist && c.(string) == infra.Enable {
								servive.PerfermanceEnable = infra.Enable
							}
						}
					}
				}
			}

			srvsi, ok := dSpec["services"]
			if ok {
				srvs, ok := srvsi.(map[string]interface{})
				if ok {
					si, exist := srvs[name]
					if exist {
						ss, ok := si.(map[string]interface{})
						if ok {
							s, exist := ss["application_service"]
							if exist {
								servive.AppEnable = infra.Enable
								servive.App = s.(string)
							}
						}
					}
				}
			}
		}

		if r.Platform == PlatformKubernetes {
			if r.Name == "computing-power" {
				servive.AppEnable = infra.Enable
				servive.App = "http://39.101.140.145:63902/"
			}

			if r.ConfigID == "5d980937-d694-4c5c-841b-8ba94155a051" {
				servive.AppEnable = infra.Enable
				servive.App = "http://39.101.140.145:19980/"
			}

		}

		run.Containers[name] = servive
		if _, ok = appyaml[r.ConfigID]; ok {
			if _, et := appyaml[r.ConfigID][name]; et {
				run.Containers[name] = appyaml[r.ConfigID][name]
			} else {
				run.Containers[name] = svc{
					PerfermanceEnable: infra.Disable,
					AppEnable:         infra.Disable,
					App:               "",
				}
			}
		}
	}

	//fmt.Printf("service %v\n",run.Containers)

	return run, nil
}
